/*
 * httprequest.h
 *
 *  Created on: Aug 28, 2011
 *      Author: anonovermind <anonovermind@gmail.com>
 */

#ifndef HTTPREQUEST_H_
#define HTTPREQUEST_H_

#include "request.h"
#include <boost/signals2.hpp>
#include <boost/asio.hpp>
#include "url.h"
#include "httpnetworkcontext.h"
#include "httpcachingresolver.h"

namespace Wishmaster2 {
namespace Network {

class HttpRequest : public Wishmaster2::Network::Request {
public:
	HttpRequest(boost::asio::io_service& service,
			HttpCachingResolver* resolver,
			int id,
			const Url& url,
			const HttpNetworkContextPtr& context);

	virtual ~HttpRequest();

	virtual int id() const;

	virtual boost::signals2::connection connectSignalFinished(const finished_signal::slot_type& finished);
	virtual boost::signals2::connection connectSignalProgress(const progress_signal::slot_type& progress);
	virtual boost::signals2::connection connectSignalError(const error_signal::slot_type& error);

	virtual void perform();
	virtual void cancel();

	virtual VectorPtr content();
	virtual std::string contentType() const;

	virtual Url url() const;

	int statusCode() const;

	void setPostBoundary(const std::string& boundary);

	std::string header(const std::string& name) const;

	virtual void setParameter(const std::string& paramName, const std::string& paramValue);
	virtual void addBinaryData(const std::string& paramName, const std::string& dataName, const std::vector<char>& data);

protected:
	void handle_resolve(const boost::system::error_code& error,
			boost::asio::ip::tcp::resolver::iterator endpoint_iterator);
	void handle_connect(const boost::system::error_code& error);
	void handle_write_header(const boost::system::error_code& error);
	void handle_headers(const boost::system::error_code& error);
	void handle_content(const boost::system::error_code& error);
	void handle_chunked(const boost::system::error_code& error);

	std::pair<std::string, std::string> parseHeaderEntry(const std::string& headerEntry);
	void parseCookies(const std::string& cookies);

	virtual boost::asio::streambuf* createRequestStreamBuf();
	virtual boost::asio::streambuf* createResponseStreamBuf();

	static char randomChar();

private:

	finished_signal m_finished;
	progress_signal m_progress;
	error_signal m_error;

	HttpCachingResolver* m_resolver;
	int m_id;
	Url m_url;
	int m_statusCode;
	boost::asio::ip::tcp::socket m_socket;
	boost::asio::streambuf* m_request;
	boost::asio::streambuf* m_response;
	VectorPtr m_content;
	int m_expectedLength;
	int m_readLength;
	std::string m_referer;
	std::string m_method;
	std::string m_boundary;

	std::map<std::string, std::string> m_params;
	struct FileDescriptor
	{
		std::string filename;
		std::vector<char> filedata;
	};
	std::map<std::string, FileDescriptor> m_files;
	std::map<std::string, std::string> m_headers;

	bool m_chunked;
	HttpNetworkContextPtr m_context;
};

} /* namespace Network */
} /* namespace Wishmaster2 */
#endif /* HTTPREQUEST_H_ */
